using CfgTable;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using System;
using System.Collections.Generic;

namespace IQIGame.Onigao.GamePlay
{
    public class UIConfirmInnerData : IReusableClass
    {
        public int id;
        public CfgNotice cfgNotice;
        public string finalDesc;
        public Action callBtnConfirm;
        public Action callBtnCancel;
        public Action callBtnClose;
        public bool canAwait;

        public uint MaxStore => 2;

        public void OnReset()
        {
            id = 0;
            cfgNotice = null;
            finalDesc = null;
            callBtnConfirm = null;
            callBtnCancel = null;
            callBtnClose = null;
            canAwait = false;
        }
    }

    public class UIConfirm : UIEntityWindow
    {
        #region Template Generate,don't modify
        protected class UIB_UIConfirm
        {
            #region ObjectBinding Generate 
            public UnityEngine.GameObject panels { protected set; get; }
            public UnityEngine.GameObject confirm { protected set; get; }
            public virtual void InitBinding(ObjectBinding __binding)
            {
                __binding.TryGetVariableValue<UnityEngine.GameObject>("panels", out var __tbv0);
                this.panels = __tbv0;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("confirm", out var __tbv1);
                this.confirm = __tbv1;
            }
            #endregion ObjectBinding Generate 
        }
        #endregion Template Generate,don't modify


        #region Window Config
        /// <summary>
        /// 静态配置
        /// </summary>
        private static UICreateConfig _createConfig = new()
        {
            prefabName = nameof(UIConfirm),
            layer = EUILayer.Normal,
        };

        /// <summary>
        /// 创建UI的配置
        /// </summary>
        public override IUICreateConfig createConfig => _createConfig;
        #endregion Window Config

        #region fields

        private const int DefaultCapacity = 2;

        private static int IDGenerator;

        private UIItemPool<UIN_Confirm> confirmPool;
        private Dictionary<int, UIConfirmInnerData> datas = new(DefaultCapacity);
        private Dictionary<int, AutoResetUniTaskCompletionSource<NoticeResultType>> _taskSourceMap = new(DefaultCapacity);

        #endregion fields

        #region properties

        protected UIB_UIConfirm ui { get; set; }

        #endregion properties

        protected override void BeforeInit()
        {
            ui = new UIB_UIConfirm();
            ui.InitBinding(this.csObjBind);
        }

        protected override void OnInit()
        {
            this.isUpdate = true;

            this.confirmPool = this.InitPool<UIN_Confirm>(this.ui.confirm);
        }

        protected override void OnShow(UIBaseData data)
        {
            //可等待模式OnShow时data为空，因为可等待模式会调用PopWindow来设值
            if (data == null)
            {
                return;
            }
            var innderData = PushData(data as UD_Confirm, false);
            AwaitShowNode(innderData).Forget();
        }

        private UIConfirmInnerData PushData(UD_Confirm ud, bool canAwait)
        {
            var innerData = ClassPool<UIConfirmInnerData>.Get();
            innerData.id = ++IDGenerator;
            innerData.cfgNotice = ud.cfgNotice;
            innerData.finalDesc = ud.finalDesc;
            innerData.callBtnConfirm = ud.callBtnConfirm;
            innerData.callBtnCancel = ud.callBtnCancel;
            innerData.callBtnClose = ud.callBtnClose;
            innerData.canAwait = canAwait;
            datas.Add(innerData.id, innerData);
            return innerData;
        }

        protected override void OnHide()
        {
            this.datas.Clear();
            foreach (var kv in _taskSourceMap)
            {
                kv.Value.TrySetCanceled();
            }
            _taskSourceMap.Clear();
        }

        protected override void OnDispose()
        {

        }

        public UniTask<NoticeResultType> PopWindow(UIBaseData data)
        {
            var d = data as UD_Confirm;
            var innderData = PushData(d, true);
            return AwaitShowNode(innderData);
        }

        private async UniTask<NoticeResultType> AwaitShowNode(UIConfirmInnerData d)
        {
            //如果前一个node在等待时，又调用了该方法，那么上一个node不会hide，还是在原状态，等待玩家操作或整个UI关闭时才会结束任务
            UIN_Confirm node = this.confirmPool.GetOne(false);

            node.Show(d.id, d.cfgNotice, d.finalDesc,
                d.callBtnConfirm, d.callBtnCancel, d.callBtnClose,
                this.OnOperationComplete);

            NoticeResultType result = NoticeResultType.None;
            //可等待才走下面的逻辑，否则直接返回None
            if (d.canAwait)
            {
                var taskSource = AutoResetUniTaskCompletionSource<NoticeResultType>.Create();
                _taskSourceMap.Add(d.id, taskSource);

                try
                {
                    result = await taskSource.Task;
                }
                catch (OperationCanceledException)
                {
                    result = NoticeResultType.CancelBySystem;
                }
                catch (Exception e)
                {
                    LogGame.LogException(e);
                    result = NoticeResultType.Exception;
                }
            }
            return result;
        }

        public void OnOperationComplete(UIN_Confirm node, NoticeResultType type)
        {
            var id = node.id;
            this.confirmPool.HideOne(node);
            if (datas.TryGetValue(id, out var innerData))
            {
                if (_taskSourceMap.TryGetValue(id, out var taskSource))
                {
                    taskSource.TrySetResult(type);
                    _taskSourceMap.Remove(id);
                }
                datas.Remove(id);
                ClassPool<UIConfirmInnerData>.Put(innerData);
            }
            if (this.datas.Count == 0)
            {
                Close();
            }
        }
    }
}
